1   /*
2    * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  
24  /*
25   * @test
26   * @bug 4495742
27   * @ignore JSSE supported cipher suites are changed with CR 6916074,
28   *     need to update this test case in JDK 7 soon
29   * @run main/timeout=180 TestAllSuites
30   * @summary Add non-blocking SSL/TLS functionality, usable with any
31   *      I/O abstraction
32   *
33   * Iterate through all the suites using both TLS and SSLv3, and turn
34   * SSLv2Hello off and on.  Exchange some bytes and shutdown.
35   *
36   * @author Brad Wetmore
37   */
38  
39  import javax.net.ssl.*;
40  import javax.net.ssl.SSLEngineResult.*;
41  import java.io.*;
42  import java.security.*;
43  import java.nio.*;
44  import java.util.*;
45  
46  public class TestAllSuites {
47  
48      private static boolean debug = false;
49  
50      private SSLContext sslc;
51      private SSLEngine ssle1;    // client
52      private SSLEngine ssle2;    // server
53  
54      private static String pathToStores = "../../../../../etc";
55      private static String keyStoreFile = "keystore";
56      private static String trustStoreFile = "truststore";
57      private static String passwd = "passphrase";
58  
59      private static String keyFilename =
60              System.getProperty("test.src", "./") + "/" + pathToStores +
61                  "/" + keyStoreFile;
62      private static String trustFilename =
63              System.getProperty("test.src", "./") + "/" + pathToStores +
64                  "/" + trustStoreFile;
65  
66      private ByteBuffer appOut1;         // write side of ssle1
67      private ByteBuffer appIn1;          // read side of ssle1
68      private ByteBuffer appOut2;         // write side of ssle2
69      private ByteBuffer appIn2;          // read side of ssle2
70  
71      private ByteBuffer oneToTwo;        // "reliable" transport ssle1->ssle2
72      private ByteBuffer twoToOne;        // "reliable" transport ssle2->ssle1
73  
74      String [][] protocols = new String [][] {
75          { "SSLv3" },
76          { "TLSv1" },
77          { "SSLv3", "SSLv2Hello"},
78          { "TLSv1", "SSLv2Hello"}
79      };
80  
81      /*
82       * Majority of the test case is here, setup is done below.
83       */
84  
85      private void createSSLEngines() throws Exception {
86          ssle1 = sslc.createSSLEngine("client", 1);
87          ssle1.setUseClientMode(true);
88  
89          ssle2 = sslc.createSSLEngine("server", 2);
90          ssle2.setUseClientMode(false);
91      }
92  
93      private void test() throws Exception {
94  
95          createSSLEngines();
96          String [] suites = ssle1.getSupportedCipherSuites();
97  
98          for (int i = 0; i < suites.length; i++) {
99              for (int j = 0; j < protocols.length; j++) {
100                 createSSLEngines();
101                 runTest(suites[i], protocols[j]);
102             }
103         }
104     }
105 
106     private void runTest(String suite, String [] protocols) throws Exception {
107 
108         boolean dataDone = false;
109 
110         System.out.println("======================================");
111         System.out.println("Testing: " + suite);
112         for (int i = 0; i < protocols.length; i++) {
113             System.out.print(protocols[i] + " ");
114         }
115 
116         /*
117          * Don't run the Kerberized suites for now.
118          */
119         if (suite.startsWith("TLS_KRB5")) {
120             System.out.println("Ignoring Kerberized suite");
121             return;
122         }
123 
124         /*
125          * Don't run the SCSV suite
126          */
127         if (suite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
128             System.out.println("Ignoring SCSV suite");
129             return;
130         }
131 
132 
133         if (!suite.contains("DH_anon")) {
134             ssle2.setNeedClientAuth(true);
135         }
136 
137         String [] suites = new String [] { suite };
138 
139         ssle1.setEnabledCipherSuites(suites);
140         ssle2.setEnabledCipherSuites(suites);
141 
142         ssle1.setEnabledProtocols(protocols);
143         ssle2.setEnabledProtocols(protocols);
144 
145         createBuffers();
146 
147         SSLEngineResult result1;        // ssle1's results from last operation
148         SSLEngineResult result2;        // ssle2's results from last operation
149 
150         Date start = new Date();
151         while (!isEngineClosed(ssle1) || !isEngineClosed(ssle2)) {
152 
153             log("----------------");
154 
155             result1 = ssle1.wrap(appOut1, oneToTwo);
156             result2 = ssle2.wrap(appOut2, twoToOne);
157 
158             log("wrap1:  " + result1);
159             log("oneToTwo  = " + oneToTwo);
160             log("");
161 
162             log("wrap2:  " + result2);
163             log("twoToOne  = " + twoToOne);
164 
165             runDelegatedTasks(result1, ssle1);
166             runDelegatedTasks(result2, ssle2);
167 
168             oneToTwo.flip();
169             twoToOne.flip();
170 
171             log("----");
172 
173             result1 = ssle1.unwrap(twoToOne, appIn1);
174             result2 = ssle2.unwrap(oneToTwo, appIn2);
175 
176             log("unwrap1: " + result1);
177             log("twoToOne  = " + twoToOne);
178             log("");
179 
180             log("unwrap2: " + result2);
181             log("oneToTwo  = " + oneToTwo);
182 
183             runDelegatedTasks(result1, ssle1);
184             runDelegatedTasks(result2, ssle2);
185 
186             oneToTwo.compact();
187             twoToOne.compact();
188 
189             /*
190              * If we've transfered all the data between app1 and app2,
191              * we try to close and see what that gets us.
192              */
193             if (!dataDone && (appOut1.limit() == appIn2.position()) &&
194                     (appOut2.limit() == appIn1.position())) {
195 
196                 checkTransfer(appOut1, appIn2);
197                 checkTransfer(appOut2, appIn1);
198 
199                 log("Closing ssle1's *OUTBOUND*...");
200                 ssle1.closeOutbound();
201                 dataDone = true;
202             }
203         }
204 
205         /*
206          * Just for grins, try closing again, make sure nothing
207          * strange is happening after we're closed.
208          */
209         ssle1.closeInbound();
210         ssle1.closeOutbound();
211 
212         ssle2.closeInbound();
213         ssle2.closeOutbound();
214 
215         appOut1.rewind();
216         appIn1.clear();
217         oneToTwo.clear();
218 
219         result1 = ssle1.wrap(appOut1, oneToTwo);
220         checkResult(result1);
221 
222         result1 = ssle1.unwrap(oneToTwo, appIn1);
223         checkResult(result1);
224 
225         System.out.println("Test Passed.");
226         System.out.println("\n======================================");
227 
228         Date end = new Date();
229         elapsed += end.getTime() - start.getTime();
230 
231     }
232 
233     static long elapsed = 0;
234 
235     private static void checkResult(SSLEngineResult result) throws Exception {
236         if ((result.getStatus() != Status.CLOSED) ||
237                 (result.getHandshakeStatus() !=
238                     HandshakeStatus.NOT_HANDSHAKING) ||
239                 (result.bytesConsumed() != 0) ||
240                 (result.bytesProduced() != 0)) {
241             throw new Exception("Unexpected close status");
242         }
243     }
244 
245     public static void main(String args[]) throws Exception {
246 
247         TestAllSuites tas;
248 
249         tas = new TestAllSuites();
250 
251         tas.createSSLEngines();
252 
253         tas.test();
254 
255         System.out.println("All Tests Passed.");
256         System.out.println("Elapsed time: " + elapsed / 1000.0);
257     }
258 
259     /*
260      * **********************************************************
261      * Majority of the test case is above, below is just setup stuff
262      * **********************************************************
263      */
264 
265     public TestAllSuites() throws Exception {
266         sslc = getSSLContext(keyFilename, trustFilename);
267     }
268 
269     /*
270      * Create an initialized SSLContext to use for this test.
271      */
272     private SSLContext getSSLContext(String keyFile, String trustFile)
273             throws Exception {
274 
275         KeyStore ks = KeyStore.getInstance("JKS");
276         KeyStore ts = KeyStore.getInstance("JKS");
277 
278         char[] passphrase = "passphrase".toCharArray();
279 
280         ks.load(new FileInputStream(keyFile), passphrase);
281         ts.load(new FileInputStream(trustFile), passphrase);
282 
283         KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
284         kmf.init(ks, passphrase);
285 
286         TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
287         tmf.init(ts);
288 
289         SSLContext sslCtx = SSLContext.getInstance("TLS");
290 
291         sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
292 
293         return sslCtx;
294     }
295 
296     private void createBuffers() {
297         // Size the buffers as appropriate.
298 
299         SSLSession session = ssle1.getSession();
300         int appBufferMax = session.getApplicationBufferSize();
301         int netBufferMax = session.getPacketBufferSize();
302 
303         appIn1 = ByteBuffer.allocateDirect(appBufferMax + 50);
304         appIn2 = ByteBuffer.allocateDirect(appBufferMax + 50);
305 
306         oneToTwo = ByteBuffer.allocateDirect(netBufferMax);
307         twoToOne = ByteBuffer.allocateDirect(netBufferMax);
308 
309         appOut1 = ByteBuffer.wrap("Hi Engine2, I'm SSLEngine1".getBytes());
310         appOut2 = ByteBuffer.wrap("Hello Engine1, I'm SSLEngine2".getBytes());
311 
312         log("AppOut1 = " + appOut1);
313         log("AppOut2 = " + appOut2);
314         log("");
315     }
316 
317     private static void runDelegatedTasks(SSLEngineResult result,
318             SSLEngine engine) throws Exception {
319 
320         if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
321             Runnable runnable;
322             while ((runnable = engine.getDelegatedTask()) != null) {
323                 log("running delegated task...");
324                 runnable.run();
325             }
326         }
327     }
328 
329     private static boolean isEngineClosed(SSLEngine engine) {
330         return (engine.isOutboundDone() && engine.isInboundDone());
331     }
332 
333     private static void checkTransfer(ByteBuffer a, ByteBuffer b)
334             throws Exception {
335         a.flip();
336         b.flip();
337 
338         if (!a.equals(b)) {
339             throw new Exception("Data didn't transfer cleanly");
340         } else {
341             log("Data transferred cleanly");
342         }
343 
344         a.position(a.limit());
345         b.position(b.limit());
346         a.limit(a.capacity());
347         b.limit(b.capacity());
348     }
349 
350     private static void log(String str) {
351         if (debug) {
352             System.out.println(str);
353         }
354     }
355 }